From 41e752879cd906767c8473bb124345e8beb190e6 Mon Sep 17 00:00:00 2001 From: Brion Vibber Date: Tue, 24 Aug 2004 08:11:46 +0000 Subject: [PATCH] Special:Log and the logging table -- unified logging scariness! Replaces the ugly, often breaking, manually archived log pages with a nice clean table which can be sorted, trimmed, viewed in pieces, etc. You can see all logged actions by some user, or affecting some page, and can combine the views of all all logs in one. There are probably still some broken things in here, but I want this committed before the patch gets any bigger. recentchanges table is altered to make rc_namespace signed so Special: links can be listed in it. --- RELEASE-NOTES | 1 + config/index.php | 1 + includes/Article.php | 13 +- includes/Image.php | 7 +- includes/LogPage.php | 229 +++++++-------------- includes/SpecialBlockip.php | 5 +- includes/SpecialIpblocklist.php | 5 +- includes/SpecialLog.php | 267 +++++++++++++++++++++++++ includes/SpecialMakesysop.php | 8 +- includes/SpecialPage.php | 1 + includes/SpecialUndelete.php | 4 +- languages/Language.php | 3 + maintenance/archives/patch-logging.sql | 32 +++ maintenance/tables.sql | 31 ++- maintenance/updaters.inc | 12 ++ 15 files changed, 435 insertions(+), 184 deletions(-) create mode 100644 includes/SpecialLog.php create mode 100644 maintenance/archives/patch-logging.sql diff --git a/RELEASE-NOTES b/RELEASE-NOTES index e3a5e458b9..45a90f1de2 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -16,6 +16,7 @@ Major changes from 1.3.x: * 'Recentchanges Patrol' to mark new edits that haven't yet been viewed * Support for faster C++ diff module (WikiDiff extension) * More scary link caching modes +* Old manually maintained log pages replaced with searchable Special:Log * ... and more! === Caveats === diff --git a/config/index.php b/config/index.php index 991e0e3607..3df6ad8cac 100644 --- a/config/index.php +++ b/config/index.php @@ -478,6 +478,7 @@ if( $conf->posted && ( 0 == count( $errs ) ) ) { do_objectcache_update(); flush(); do_categorylinks_update(); flush(); do_image_name_unique_update(); flush(); + do_logging_update(); flush(); if ( isTemplateInitialised() ) { print "Template namespace already initialised\n"; diff --git a/includes/Article.php b/includes/Article.php index 03b2cf9790..09742e060f 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -8,7 +8,6 @@ # moved to separate EditPage and CacheManager classes. require_once ( 'CacheManager.php' ); -include_once ( 'SpecialValidate.php' ) ; $wgArticleCurContentFields = false; $wgArticleOldContentFields = false; @@ -1088,6 +1087,7 @@ class Article { function validate () { global $wgOut, $wgUseValidation; if( $wgUseValidation ) { + require_once ( 'SpecialValidate.php' ) ; $wgOut->setPagetitle( wfMsg( 'validate' ) . ': ' . $this->mTitle->getPrefixedText() ); $wgOut->setRobotpolicy( 'noindex,follow' ); if( $this->mTitle->getNamespace() != 0 ) { @@ -1210,11 +1210,11 @@ class Article { ), 'Article::protect' ); - $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext' ) ); + $log = new LogPage( 'protect' ); if ( $limit === '' ) { - $log->addEntry( wfMsg( 'unprotectedarticle', $this->mTitle->getPrefixedText() ), $reason ); + $log->addEntry( 'unprotect', $this->mTitle, $reason ); } else { - $log->addEntry( wfMsg( 'protectedarticle', $this->mTitle->getPrefixedText() ), $reason ); + $log->addEntry( 'protect', $this->mTitle, $reason ); } $wgOut->redirect( $this->mTitle->getFullURL() ); return; @@ -1592,9 +1592,8 @@ class Article { $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) ); # Log the deletion - $log = new LogPage( wfMsg( 'dellogpage' ), wfMsg( 'dellogpagetext' ) ); - $art = $this->mTitle->getPrefixedText(); - $log->addEntry( wfMsg( 'deletedarticle', $art ), $reason ); + $log = new LogPage( 'delete' ); + $log->addEntry( 'delete', $this->mTitle, $reason ); # Clear the cached article id so the interface doesn't act like we exist $this->mTitle->resetArticleID( 0 ); diff --git a/includes/Image.php b/includes/Image.php index 3b9ff5d9e8..5a1af68dbc 100644 --- a/includes/Image.php +++ b/includes/Image.php @@ -443,11 +443,8 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source $descTitle->invalidateCache(); } - $log = new LogPage( wfMsg( 'uploadlogpage' ), wfMsg( 'uploadlogpagetext' ) ); - $da = wfMsg( 'uploadedimage', '[[:' . $wgLang->getNsText( - Namespace::getImage() ) . ":{$name}|{$name}]]" ); - $ta = wfMsg( 'uploadedimage', $name ); - $log->addEntry( $da, $desc, $ta ); + $log = new LogPage( 'upload' ); + $log->addEntry( 'upload', $descTitle, $desc ); } function wfImageArchiveUrl( $name ) diff --git a/includes/LogPage.php b/includes/LogPage.php index 0e5aea962c..52603564d3 100644 --- a/includes/LogPage.php +++ b/includes/LogPage.php @@ -1,58 +1,38 @@ +# http://www.mediawiki.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# http://www.gnu.org/copyleft/gpl.html + +# Class to simplify the use of log pages. +# The logs are now kept in a table which is easier to manage and trim +# than ever-growing wiki pages. class LogPage { - /* private */ var $mTitle, $mContent, $mContentLoaded, $mId, $mComment; - var $mUpdateRecentChanges ; + /* private */ var $type, $action, $comment; + var $updateRecentChanges = true; - function LogPage( $title, $defaulttext = "" ) - { - # For now, assume title is correct dbkey - # and log pages always go in Wikipedia namespace - $this->mTitle = str_replace( ' ', '_', $title ); - $this->mId = 0; - $this->mUpdateRecentChanges = true ; - $this->mContentLoaded = false; - $this->getContent( $defaulttext ); + function LogPage( $type ) { + # Type is one of 'block', 'protect', 'rights', 'delete', 'upload' + $this->type = $type; } - function getContent( $defaulttext = "" ) - { - $fname = 'LogPage::getContent'; - - $dbw =& wfGetDB( DB_MASTER ); - $s = $dbw->getArray( 'cur', - array( 'cur_id','cur_text','cur_timestamp' ), - array( 'cur_namespace' => Namespace::getWikipedia(), 'cur_title' => $this->mTitle ), - $fname, 'FOR UPDATE' - ); - - if( $s !== false ) { - $this->mId = $s->cur_id; - $this->mContent = $s->cur_text; - $this->mTimestamp = wfTimestamp(TS_MW,$s->cur_timestamp); - } else { - $this->mId = 0; - $this->mContent = $defaulttext; - $this->mTimestamp = wfTimestamp(TS_MW); - } - $this->mContentLoaded = true; # Well, sort of - - return $this->mContent; - } - - function getTimestamp() - { - if( !$this->mContentLoaded ) { - $this->getContent(); - } - return $this->mTimestamp; - } - - function saveContent() - { + function saveContent() { if( wfReadOnly() ) return; global $wgUser; @@ -61,127 +41,62 @@ class LogPage { $dbw =& wfGetDB( DB_MASTER ); $uid = $wgUser->getID(); - if( !$this->mContentLoaded ) return false; - $this->mTimestamp = $now = wfTimestampNow(); - $won = wfInvertTimestamp( $now ); - if($this->mId == 0) { - $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); - - # Note: this query will deadlock if another thread has called getContent(), - # at least in MySQL 4.0.17 InnoDB - $dbw->insertArray( 'cur', - array( - 'cur_id' => $seqVal, - 'cur_timestamp' => $dbw->timestamp($now), - 'cur_user' => $uid, - 'cur_user_text' => $wgUser->getName(), - 'cur_namespace' => NS_WIKIPEDIA, - 'cur_title' => $this->mTitle, - 'cur_text' => $this->mContent, - 'cur_comment' => $this->mComment, - 'cur_restrictions' => 'sysop', - 'inverse_timestamp' => $won, - 'cur_touched' => $dbw->timestamp($now), - ), $fname - ); - $this->mId = $dbw->insertId(); - } else { - $dbw->updateArray( 'cur', - array( /* SET */ - 'cur_timestamp' => $dbw->timestamp($now), - 'cur_user' => $uid, - 'cur_user_text' => $wgUser->getName(), - 'cur_text' => $this->mContent, - 'cur_comment' => $this->mComment, - 'cur_restrictions' => 'sysop', - 'inverse_timestamp' => $won, - 'cur_touched' => $dbw->timestamp($now), - ), array( /* WHERE */ - 'cur_id' => $this->mId - ), $fname - ); - } + $this->timestamp = $now = wfTimestampNow(); + $dbw->insertArray( 'logging', + array( + 'log_type' => $this->type, + 'log_action' => $this->action, + 'log_timestamp' => $dbw->timestamp( $now ), + 'log_user' => $uid, + 'log_namespace' => $this->target->getNamespace(), + 'log_title' => $this->target->getDBkey(), + 'log_comment' => $this->comment + ), $fname + ); # And update recentchanges - if ( $this->mUpdateRecentChanges ) { - $titleObj = Title::makeTitle( Namespace::getWikipedia(), $this->mTitle ); - RecentChange::notifyLog( $now, $titleObj, $wgUser, $this->mComment ); + if ( $this->updateRecentChanges ) { + $rcComment = $this->actionText; + if( '' != $this->comment ) { + $rcComment .= ': ' . $this->comment; + } + $titleObj = Title::makeTitle( NS_SPECIAL, 'Log/' . $this->type ); + RecentChange::notifyLog( $now, $titleObj, $wgUser, $rcComment ); } return true; } - function addEntry( $action, $comment, $textaction = '' ) - { - global $wgLang, $wgUser; - - $comment_esc = wfEscapeWikiText( $comment ); - - $this->getContent(); - - $ut = $wgUser->getName(); - $uid = $wgUser->getID(); - if( $uid ) { - $ul = '[[' . - $wgLang->getNsText( Namespace::getUser() ) . - ":{$ut}|{$ut}]]"; - } else { - $ul = $ut; - } - - # Use the wiki-wide default date format instead of the user's setting - $d = $wgLang->timeanddate( wfTimestampNow(), false, MW_DATE_DEFAULT ); - - if( preg_match( "/^(.*?)